package gestor;

import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAException;
import jade.lang.acl.ACLMessage;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.JOptionPane;
import util.DF;

public class Agente extends Agent {
	private FrmGUI frmGUI = null;
	final static public String serviceType = "gestor";
	protected String nome;

	protected static Map<String, Reputacao> registo = new TreeMap<String, Reputacao>();

	@Override
	protected void setup() {
		boolean success;
		nome = getLocalName();

		// Verificar no DF se é o único gestor
		success = checkIfOnlyManager();
		if(!success) return;

		// Registar no DF
		success = registerServiceInDF();
		if(!success) return;

		// Mostrar a interface gráfica
		frmGUI = new FrmGUI(this);
		frmGUI.setVisible(true);

		iniciarGestao();
	}

	@Override
	protected void takeDown() {
		DF.deregister(this);
		if(frmGUI != null) {
			frmGUI.dispose();
			frmGUI = null;
		}
	}

	protected void stop() {
		frmGUI = null;
		doDelete();
	}

	private boolean checkIfOnlyManager() {
  		try {
			DFAgentDescription[] results = DF.search(this, serviceType);

			if(results.length > 0) {
				JOptionPane.showMessageDialog(null, "Já existe um agente gestor!", nome, JOptionPane.ERROR_MESSAGE);
				doDelete();
				return false;
			}
			else
				return true;

		} catch (FIPAException ex) {
			JOptionPane.showMessageDialog(null, "Erro ao verificar a presença de mais agentes gestores no DF:\n" + ex.getMessage(), nome, JOptionPane.ERROR_MESSAGE);
			doDelete();
			return false;
		}
	}

	private boolean registerServiceInDF() {
		try {
			DF.register(this, nome, serviceType);
			return true;
		} catch (FIPAException ex) {
			JOptionPane.showMessageDialog(null, "Erro ao registar o serviço gestor no DF:\n" + ex.getMessage(), nome, JOptionPane.ERROR_MESSAGE);
			doDelete();
			return false;
		}
	}

	private void iniciarGestao() {
		addBehaviour(new CyclicBehaviour(this) {
			public void action() {
				// Receber mensagem
				ACLMessage msg = myAgent.receive();

				if(msg != null) {
					ACLMessage reply = msg.createReply();
					
					// Verificar tipo de mensagem
					if(msg.getPerformative() == ACLMessage.REQUEST) {
						
						
						// Pedido de reputação de agente
						if(msg.getOntology().equals("reputacao")) {
							String nome = msg.getContent();

							Reputacao rep = registo.get(nome);
							if(rep == null) // Agente ainda não existe no registo
								rep = new Reputacao(0, 0);

							reply.setPerformative(ACLMessage.INFORM);
							reply.setOntology("reputacao");
							reply.setContent(rep.toString());
						}
						else {
							reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
							reply.setOntology("error");
							reply.setContent("unknown-ontology");
						}
					}
					else if(msg.getPerformative() == ACLMessage.INFORM) {
						// Aumentar ou diminuir reputação de agente
						if(msg.getOntology().equals("positivo")) {
							String nome = msg.getContent();

							Reputacao rep = registo.get(nome);
							if(rep == null) // Agente ainda não existe no registo
								rep = new Reputacao(0, 0);
							else
								registo.remove(nome);
							rep.addPositive();
							registo.put(nome, rep);
							frmGUI.refreshList();

							reply.setPerformative(ACLMessage.CONFIRM);
							reply.setOntology("positivo");
							reply.setContent("ok");
						}
						else if(msg.getOntology().equals("negativo")) {
							String nome = msg.getContent();

							Reputacao rep = registo.get(nome);
							if(rep == null) // Agente ainda não existe no registo
								rep = new Reputacao(0, 0);
							else
								registo.remove(nome);
							rep.addNegative();
							registo.put(nome, rep);
							frmGUI.refreshList();

							reply.setPerformative(ACLMessage.CONFIRM);
							reply.setOntology("negativo");
							reply.setContent("ok");
						}
						else {
							reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
							reply.setOntology("error");
							reply.setContent("unknown-ontology");
						}
					}
					else {
						reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
						reply.setOntology("error");
						reply.setContent("unknown-performative");
					}

					myAgent.send(reply);
				}
			}
		} );
	}

	static public boolean getRep(String nome) {
		if(registo.get(nome).getPositive() < registo.get(nome).getNegative())
			return false;
		else 
			return true;
	}
}